<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------

// 应用公共文件
use app\common\facade\CategoryFacade;
use app\common\model\UrlModel;
use app\common\service\UploadService;

error_reporting(E_ERROR | E_WARNING | E_PARSE);

define('ART_TYPE_NORMAL', 1);
define('ART_TYPE_TOP', 2);
define('ART_TYPE_HOT', 4);
define('ART_TYPE_RECOMMEND', 8);

define('USE_SEC_PASSWORD', 1);

// TODO 上线前修改此值
define('PASSWORD_HASH_PREFIX', 'HashPrefixForPassword');

function force_json_decode($string)
{
    if (is_array($string)) return $string;
    if (empty($string)) return [];

    $json = @json_decode($string, true);
    return empty($json) ? [] : $json;
}

function shortUrl($fullUrl)
{
    return UrlModel::shortUrl($fullUrl);
}

function indexurl($channel_name, $isShort = true, $domain = false)
{
    $url = url('index/channel/index', ['channel_name' => $channel_name], false, $domain);
    return $isShort ? shortUrl($url) : $url;
}
function listurl($cate_name, $channel_name = '', $isShort = true, $domain = false)
{
    $isTop = false;
    if (empty($channel_name)) {
        $topCate = CategoryFacade::getTopCategory($cate_name);
        if (!empty($topCate)) {
            $channel_name = $topCate['name'];
            $isTop = $topCate['is_top'];
        } else {
            $channel_name = $cate_name;
        }
    }
    if ($cate_name == $channel_name) $cate_name = '';
    else {
        if (empty($topCate)) {
            $topCate = CategoryFacade::findCategory($channel_name);
            if (!empty($topCate)) {
                $isTop = $topCate['is_top'];
            }
        }
        if ($isTop) {
            $channel_name = '';
        }
    }
    $url = url('index/channel/list', ['channel_name' => $channel_name, 'cate_name' => $cate_name], false, $domain);
    return $isShort ? shortUrl($url) : $url;
}
function viewurl($art, $channel_name = '', $isShort = true, $domain = false)
{
    $isTop = false;
    if (empty($channel_name)) {
        if (!empty($art['channel_name'])) {
            $channel_name = $art['channel_name'];
        } elseif (!empty($art['category_name'])) {
            $topCate = CategoryFacade::getTopCategory($art['category_name']);
            if (!empty($topCate)) {
                $channel_name = $topCate['name'];
                $isTop = $topCate['is_top'];
            }
        } else {
            $cate = CategoryFacade::findCategory($art['cate_id']);
            if (!empty($cate)) {
                if ($cate['pid'] == 0) {
                    $channel_name = $cate['name'];
                    $isTop = $cate['is_top'];
                } else {
                    $topCate = CategoryFacade::getTopCategory($cate['pid']);
                    $channel_name = $topCate['name'];
                    $isTop = $topCate['is_top'];
                }
                $art['category_name'] = $cate['name'];
            }
        }
        if (empty($channel_name)) {
            $channel_name = $art['category_name'];
        }
    }
    if ($art['category_name'] == $channel_name) $channel_name = '';
    else {
        if (empty($topCate)) {
            $topCate = CategoryFacade::findCategory($channel_name);
            if (!empty($topCate)) {
                $isTop = $topCate['is_top'];
            }
        }
        if ($isTop) {
            $channel_name = '';
        }
    }

    // name为空则取id
    $name = empty($art['name']) ? ('a-' . $art['id']) : $art['name'];
    $url = url('index/channel/view', ['channel_name' => $channel_name, 'cate_name' => $art['category_name'], 'article_name' => $name], true, $domain);
    return $isShort ? shortUrl($url) : $url;
}

/**
 * 根据配置输出本地图片路径或远程oss路径
 * @param $src
 * @param string $args
 * @return string
 */
function media($src, $args)
{
    if (empty($src)) return $src;
    return UploadService::thumb($src, $args);
}

/**
 * 完整输出附件的url
 * @param $src
 * @return string
 */
function local_media($src)
{
    if (empty($src)) return $src;
    $src = ltrim($src, '.');
    if (strpos($src, '/') === 0 || strpos($src, '://') === false) {
        return url('/', '', false, true) . ltrim($src, '/\\');
    }
    return $src;
}

/**
 * tp已支持下载输出
 * @param $data
 * @param $filename
 * @param $isContent
 * @param $mime
 * @return \think\Response
 */
function file_download($data, $filename = '', $isContent = true, $mime = '')
{
    /**
     * @var think\response\Download
     */
    $response = \think\Response::create($data ?: $filename, 'download', 200);
    if ($mime) {
        $response->mimeType($mime);
    }
    if ($isContent) {
        $response->isContent(true);
    }
    if ($filename) {
        $response->name($filename);
    }
    return $response;
}

/** =====================================  固态数据类函数  ===================================== **/
/**
 * 小标签的样式
 * @return array
 */
function getTextStyles()
{
    return ['secondary', 'primary', 'info', 'success', 'warning', 'danger'];
}
function getMoneyFields($withall = true)
{
    $fields = [
        'all' => lang('All'),
        'money' => lang('Balance'),
        'credit' => lang('Credit'),
        'reward' => lang('Reward')
    ];
    if (!$withall) unset($fields['all']);
    return $fields;
}

function getLogTypes($withall = true, $filter = null)
{
    $fields = [
        'all' => lang('All'),
        'system' => lang('System Opt.'),
        'consume' => lang('Consume'),
        'recharge' => lang('Recharge'),
        'commission' => lang('Commission'),
        'refund' => lang('Refund'),
        'transout' => lang('Transfer out'),
        'transin' => lang('Transfer in'),
        'consume_send' => lang('Consume Send'),
    ];
    if (!$withall) unset($fields['all']);
    if ($filter !== null) {
        if (is_string($filter)) {
            $filter = array_map('trim', explode(',', $filter));
        }
        foreach ($fields as $k => $v) {
            if ($k == 'all') continue;
            if (!in_array($k, $filter)) {
                unset($fields[$k]);
            }
        }
    }
    return $fields;
}
function getMemberTypes()
{
    return [
        1 => lang('Member'),
        2 => lang('Employee')
    ];
}

function getWechatTypes()
{
    return [
        'subscribe' => '关注回复消息',
        'resubscribe' => '二次关注回复消息',
        'default' => '默认回复',
        'keyword' => '关键字回复',
        'click' => '点击事件回复'
    ];
}
function getWechatReplyTypes()
{
    return [
        'text' => '文本消息',
        'news' => '图文消息',
        'image' => '图片消息',
        'custom' => '托管消息'
    ];
}
function getWechatMaterialTypes()
{
    return [
        'image' => '图片',
        'voice' => '语音',
        'video' => '视频',
        'article' => '图文'
    ];
}
function getArticleTypes()
{
    return [
        ART_TYPE_NORMAL => lang('Normal'),
        ART_TYPE_TOP => lang('Top'),
        ART_TYPE_HOT => lang('Hot'),
        ART_TYPE_RECOMMEND => lang('Recommend')
    ];
}

function getOauthTypes()
{
    return [
        'facebook' => 'Facebook',
        'github' => 'GitHub',
        'google' => 'Google',
        'linkedin' => 'Linkedin',
        'weibo' => 'Weibo',
        'qq' => 'QQ',
        'wechat' => 'WeChat',
        'wechat_open' => 'Wechat Open',
        'douban' => 'Douban',
        'wework' => 'WeWork',
        'outlook' => 'Outlook',
    ];
}

function toDto($array, $map = [])
{
    if (empty($array)) {
        return new \stdClass();
    }
    if (!is_array($array)) {
        return $array;
    }
    $newdata = [];
    foreach ($array as $k => $v) {
        if (isset($map[$k])) {
            $newdata[$map[$k]] = $v;
        } else {
            $newdata[camelize(str_replace('-', '_', $k))] = $v;
        }
    }
    return $newdata;
}

function settingGroups($name = '')
{
    $groups = array(
        'common' => lang('Common Settings'),
        'member' => lang('Member Settings'),
        'third' => lang('Third Settings'),
        //'sign' => lang('Sign Settings'),
        'advance' => lang('Advance Settings'),
    );
    if (empty($name)) {
        return $groups;
    } else {
        return $groups[$name];
    }
}

/**
 * 获取配置字段类型
 * @param $key string 类型
 * @return string|array
 */
function settingTypes($key = '')
{
    $types = array();
    $types['text'] = lang('Text Field');
    $types['number'] = lang('Numberic');
    $types['bool'] = lang('True False');
    $types['radio'] = lang('Radio Box');
    $types['check'] = lang('Check Box');
    $types['select'] = lang('Select');
    $types['textarea'] = lang('Textarea');
    $types['location'] = lang('Location Picker');
    $types['image'] = lang('Upload Image');
    $types['json'] = lang('Json');
    $types['array'] = lang('Array');
    $types['html'] = lang('Editor');

    if (empty($key)) {
        return $types;
    } else {
        return isset($types[$key]) ? $types[$key] : '-';
    }
}

function banklist($withcode = false)
{
    $banklist = array(
        '工商银行' => '1002',
        '农业银行' => '1005',
        '中国银行' => '1026',
        '建设银行' => '1003',
        '招商银行' => '1001',
        '邮储银行' => '1066',
        '交通银行' => '1020',
        '浦发银行' => '1004',
        '民生银行' => '1006',
        '兴业银行' => '1009',
        '平安银行' => '1010',
        '中信银行' => '1021',
        '华夏银行' => '1025',
        '广发银行' => '1027',
        '光大银行' => '1022',
        '北京银行' => '4836',
        '宁波银行' => '1056',
        '上海银行' => '1024',

    );
    if ($withcode) {
        return $banklist;
    }
    return array_keys($banklist);
}

function payTypes($type = '')
{
    $types = array(
        'wechat' => lang('Wechat Pay'),
        'alipay' => lang('Alipay '),
        'unioncard' => lang('Unionpay'),
    );
    if (empty($type)) {
        return $types;
    } else {
        return $types[$type];
    }
}


/** =====================================  模板类函数  ===================================== **/

function my_implode($arr, $separator = ',', $key = 'title')
{
    if (empty($arr)) {
        return '';
    }
    if (!is_array($arr)) {
        return strval($arr);
    }

    if (is_array(current($arr))) {
        return implode($separator, array_column($arr, $key));
    }
    return implode($separator, $arr);
}

function showAddress($address)
{
    $str = '';
    if (!empty($address)) {
        $str  = $address['receive_name'] . '/' . $address['mobile'];
        if (!empty($address['country'])) $str .= '/' . $address['country'];
        if (!empty($address['province'])) $str .= '/' . $address['province'];
        if (!empty($address['city'])) $str .= '/' . $address['city'];
        if (!empty($address['area'])) $str .= '/' . $address['area'];
        if (!empty($address['street'])) $str .= '/' . $address['street'];
        if (!empty($address['address'])) $str .= '/' . $address['address'];
    }
    return $str;
}

/**
 * 显示金额 (除以 100)
 * @param $amount
 * @return float|int
 */
function showmoney($amount)
{
    return number_format(round($amount / 100, 2), 2);
}

/**
 * 显示卡号
 * @param $cardno
 * @param int $pos
 * @param bool $fulllen
 * @return string
 */
function showcardno($cardno, $pos = 6, $fulllen = false)
{
    $l = strlen($cardno) - $pos;
    return str_repeat('*', $fulllen ? $l : 3) . substr($cardno, $l);
}

function fmtCardno($cardno)
{
    return $cardno;
}

function showcashtype($type)
{
    switch ($type) {
        case 'wechat':
            return lang('Wechat');
        case 'alipay':
            return lang('Alipay');
        default:
            return lang('Unioncard');
    }
}

/**
 * 根据数据的最低价和最高价显示范围
 * @param $row
 * @return string
 */
function show_price($row)
{
    $price = $row['min_price'];
    if ($row['max_price'] > $row['min_price']) {
        $price .= ' ~ ' . $row['min_price'];
    }
    return $price;
}

/**
 * 仅转换参数，方便调用
 * @param $time
 * @param $replace
 * @param $format
 * @return false|string
 */
function showdate($time, $replace = '-', $format = 'Y-m-d H:i:s')
{
    if (!empty($replace)) {
        if ($replace != '-') {
            $format = $replace;
            $replace = '';
        }
    }
    return $time == 0 ? $replace : date($format, $time);
}


/**
 * 时间对比
 * @param $time int    对比的时间（时间戳）
 * @param $nowTime int 目前时间（时间戳）
 * @param $empty string 时间为空时的替换字符串
 * @return string
 */
function friendlytime($time = 0, $nowTime = 0, $empty = '-')
{
    if (!$time) return $empty;
    if (!$nowTime) $nowTime = time();
    $dif = $nowTime - $time;
    if ($dif < 60)
        return lang('Just now');
    $dif = $dif / 60;
    if (1 <= $dif && $dif < 60)
        return intval($dif) . ' ' . lang('minutes ago');
    $dif = $dif / 60;
    if (1 <= $dif && $dif < 24)
        return intval($dif) . ' ' . lang('hours ago');
    //最多显示3天前
    $dif = $dif / 24;
    if (1 <= $dif && $dif <= 3)
        return intval($dif) . ' ' . lang('days ago');
    if (date('Y', $time) == date('Y', $nowTime))
        return date('m-d', $time);
    return date('Y-m-d', $time);
}

/**
 * 留言状态
 * @param $status int
 * @param bool $wrap
 * @return string
 */
function feedback_status($status, $wrap = true)
{
    $statusText = array(lang('Unaudited'), lang('Audited'), lang('Hidden'));

    return $wrap ? wrap_label($statusText[$status], status_type($status)) : $statusText[$status];
}

/**
 * 审核状态
 * @param $status
 * @param bool $wrap
 * @return mixed
 */
function audit_status($status, $wrap = true)
{
    $statusText = array(lang('Unaudited'), lang('Confirmed'), lang('Invalid'));
    $statusText[-1] = lang('Invalid');
    return $wrap ? wrap_label($statusText[$status], status_type($status)) : $statusText[$status];
}

/**
 * 显示状态
 * @param $status
 * @param bool $wrap
 * @return mixed
 */
function show_status($status, $wrap = true)
{
    $statusText = array(lang('Hidden'), lang('Shown'));
    $statusText[-1] = lang('Invalid');
    return $wrap ? wrap_label($statusText[$status], status_type($status)) : $statusText[$status];
}
function status_type($status)
{
    return $status >= 0 ? ['warning', 'success', 'secondary'][$status] : 'secondary';
}

/**
 * 获取订单状态
 * @param $status
 * @return string
 */
function get_order_status($status)
{
    switch ($status) {
        case "-3":
            return lang('Refunding');
        case "-2":
            return lang('Cancelled');
        case "-1":
            return lang('Invalid');
        case "0":
            return lang('Unpaid');
        case "1":
            return lang('Unshipped');
        case "2":
            return lang('Unreceived');
        case "3":
            return lang('Unevaluate');
        case "4":
            return lang('Completed');
        default:
            return lang('Unknown');
    }
    return lang('Unknown');
}
/**
 * 订单状态
 * @param $status
 * @param bool $wrap
 * @return string
 */
function order_status($status, $wrap = true)
{
    $style = 'secondary';
    switch ($status) {
        case "0":
            $style = 'warning';
            break;
        case "1":
            $style = 'danger';
            break;
        case "2":
            $style = 'secondary';
            break;
        case "3":
            $style = 'info';
            break;
        case "4":
            $style = 'success';
            break;
        default:
            $style = 'secondary';
    }
    return $wrap ? wrap_label(get_order_status($status), $style) : get_order_status($status);
}
function money_type($type, $wrap = true)
{
    switch ($type) {
        case "money":
            return $wrap ? wrap_label(lang('Balance'), 'success') : lang('Balance');
        case "credit":
            return $wrap ? wrap_label(lang('Credit'), 'info') : lang('Credit');
        case "reward":
            return $wrap ? wrap_label(lang('Reward'), 'warning') : lang('Reward');
        default:
            return $wrap ? wrap_label(lang('Unknown'), 'secondary') : lang('Unknown');
    }
    return $wrap ? wrap_label(lang('Unknown'), 'secondary') : lang('Unknown');
}
function award_status($status, $wrap = true)
{
    switch ($status) {
        case "1":
            return $wrap ? wrap_label(lang('Gived'), 'success') : lang('Gived');
        case "-1":
            return $wrap ? wrap_label(lang('Canceled'), 'secondary') : lang('Canceled');
        case "0":
            return $wrap ? wrap_label(lang('Waiting'), 'warning') : lang('Waiting');
        default:
            $wrap ? wrap_label(lang('Unknown'), 'default') : lang('Unknown');
    }
    return $wrap ? wrap_label(lang('Unknown'), 'default') : lang('Unknown');
}
function wrap_label($text, $type = 'secondary')
{
    return "<span class=\"badge badge-$type\">$text</span>";
}

function print_remark($data)
{
    if (!empty($data) && !is_array($data)) {
        $datarr = @json_decode($data);
    }
    if (is_array($datarr)) {
        $temp = array_shift($datarr);
        return call_user_func('lang', $temp, $datarr);
    }
    return $data;
}

function masktext($text, $prelen = 3, $suflen = 4, $midmax = 4)
{
    $l = mb_strlen($text);
    $masklen = min($l - $prelen - $suflen, $midmax);
    return mb_substr($text, 0, $prelen) . ($masklen > 0 ? str_repeat('*', $masklen) : '') . mb_substr($text, $l - $suflen);
}

function maskphone($phone)
{
    if (empty($phone)) return $phone;
    $l = strlen($phone);
    $masklen = min($l - 7, 4);
    return substr($phone, 0, 3) . str_repeat('*', $masklen) . substr($phone, $l - 4);
}

function maskemail($email)
{
    if (empty($email) || strpos($email, '@') < 1) return '';
    $part = explode('@', $email);
    $l = strlen($part[0]);
    if ($l <= 3) $l = 5;
    return substr($part[0], 0, 3) . str_repeat('*', $l - 3) . '@' . $part[1];
}

function getWeek($d)
{
    $time = strtotime($d);
    $w = date('N', $time);
    static $weeks = array('', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日');
    return $weeks[intval($w)];
}

/**
 * 过滤emoji字符
 * @param $str
 * @param $replace
 * @return mixed
 */
function filter_emoji($str, $replace = '')
{
    $str = preg_replace_callback(
        '/./u',
        function (array $match) use ($replace) {
            return strlen($match[0]) >= 4 ? $replace : $match[0];
        },
        $str
    );
    return $str;
}

function white2br($str)
{
    return preg_replace('/\s+/', '<br />', $str);
}

/**
 * 字符串截取
 * @param $str
 * @param $len
 * @param string $dot
 * @return mixed|string
 */
function cutstr($str, $len, $dot = '...', $triptags = true)
{
    if ($triptags) {
        $str = trim(strip_tags($str, ''));
    }

    if (mb_strlen($str) <= $len + 2) {
        return $str;
    }

    $dstr = html_entity_decode($str);
    if (mb_strlen($dstr) <= $len + 2) {
        return $str;
    }
    $hasDecode = mb_strlen($dstr) != mb_strlen($str);
    if (strpos($dstr, ' ') !== false || strpos($dstr, '\t') !== false || strpos($dstr, "\n") !== false || strpos($dstr, "\r") !== false) {
        $dstr = preg_replace('/\s+/', ' ', $dstr);
    }
    $substr = mb_substr($dstr, 0, $len);
    if ($hasDecode) {
        $substr = htmlentities($substr);
    }
    return $substr . $dot;
}

/**
 * 普通文本转换为段落
 * @param mixed $string 
 * @return string|string[] 
 */
function nl2p($string)
{
    if (empty($string)) return '';

    $html = "<p>" . implode("</p><p>", array_map('trim', explode("\n", trim($string)))) . "</p>";

    return str_replace('<p></p>', '', $html);
}

/** =====================================  数据类函数  ===================================== **/

/**
 * 获取翻译到指定语言的数据
 * @param $data
 * @param $table
 * @param string $key
 * @param string $lang 默认当前语言
 * @return array
 */
function translate($data, $table, $key = 'id', $lang = '')
{
    return \app\common\facade\TranslateFacade::trans_list($data, $table, $key, $lang);
}

/**
 * 获取指定行或字段的翻译
 * @param $table
 * @param $key
 * @param $field
 * @param string $lang
 * @return array|string
 */
function get_translate($table, $key, $field = '', $lang = '')
{
    return \app\common\facade\TranslateFacade::get_trans($table, $key, $field, $lang);
}


function getMemberLevels($force = false)
{
    return \app\common\model\MemberLevelModel::getCacheData($force);
}
function getMemberLevel($level_id)
{
    $levels = getMemberLevels();
    return $levels[$level_id] ?: [];
}
function getLevelConfig($levels)
{
    $configs = array(
        'commission_layer' => 0
    );
    foreach ($levels as $level) {
        foreach ($configs as $k => $v) {
            $configs[$k] = max($v, $level[$k]);
        }
    }
    return $configs;
}

function getDefaultLevel()
{
    $levels = getMemberLevels();
    foreach ($levels as $level) {
        if ($level['is_default']) {
            return $level['level_id'];
        }
    }
    return 0;
}



/**
 * 操作日志
 * @param $uid
 * @param $action string|array 操作名 或 [操作名,关联id]
 * @param $result bool 操作结果
 * @param string|array $remark
 * @param string $tbl
 * @return int|string
 */
function user_log($uid, $action, $result, $remark = '', $tbl = 'member')
{
    $other_id = 0;
    if (is_array($action)) {
        $other_id = $action[1];
        $action = $action[0];
    }
    $datas = [];

    $data = [
        'create_time' => time(),
        $tbl . '_id' => $uid,
        'other_id' => $other_id,
        'ip' => app()->request->ip(),
        'action' => $action,
        'result' => intval($result),
        'remark' => json_encode(is_array($remark) ? $remark : [$remark], JSON_UNESCAPED_UNICODE)
    ];
    if ($tbl === 'member') {
        $data['model'] = request()->module();
    }
    if (is_array($other_id)) {
        foreach ($other_id as $id) {
            $data['other_id'] = $id;
            $datas[] = $data;
        }
    } else {
        $datas[] = $data;
    }
    return \think\Db::name($tbl . 'Log')->insertAll($datas);
}

/**
 * 金额变动 支持批量处理
 * charge 充值/赠送 cash 提现/提现失败
 * @param $uid
 * @param $money
 * @param $reson
 * @param string $type
 * @param int $from_id
 * @param string $field
 * @return bool|mixed
 */
function money_log($uid, $money, $reson, $type = '', $from_id = 0, $field = 'money')
{
    if ($money == 0) return true;
    $fields = getMoneyFields();
    if (is_string($from_id) && isset($fields[$from_id])) {
        $field = $from_id;
        $from_id = 0;
    }
    if ($field == 'all' || !isset($fields[$field])) return false;

    if (!is_array($uid)) {
        $uid = idArr($uid);
    }
    if (count($uid) > 500) {
        $uid_groups = array_chunk($uid, 500);
        $returns = [];
        foreach ($uid_groups as $uids) {
            $returns = array_merge($returns, money_log($uids, $money, $reson, $type, $from_id, $field));
        }
        return $returns;
    }

    $logs = [];
    $members = \think\Db::name('member')->field('id,username,' . $field)
        ->whereIn('id', $uid)->select();
    $time = time();
    if ($money > 0) {
        $result = \think\Db::name('member')->whereIn('id', $uid)
            ->setInc($field, $money);
        foreach ($members as $member) {
            $logs[] = [
                'create_time' => $time,
                'member_id' => $member['id'],
                'from_member_id' => $from_id,
                'type' => $type,
                'before' => $member[$field],
                'amount' => $money,
                'after' => $member[$field] + $money,
                'field' => $field,
                'reson' => $reson
            ];
        }
    } else {
        $decMoney = abs($money);
        $result = \think\Db::name('member')->whereIn('id', $uid)
            ->where($field, '>=', $decMoney)
            ->setDec($field, $decMoney);
        foreach ($members as $member) {
            if ($member[$field] >= $decMoney) {
                $logs[] = [
                    'create_time' => time(),
                    'member_id' => $member['id'],
                    'from_member_id' => $from_id,
                    'type' => $type,
                    'before' => $member[$field],
                    'amount' => $money,
                    'after' => $member[$field] + $money,
                    'field' => $field,
                    'reson' => $reson
                ];
            }
        }
    }
    if ($result) {
        \think\Db::name('memberMoneyLog')->insertAll($logs);
        return array_column($logs, 'member_id');
    } else {
        return false;
    }
}

function money_force_log($uid, $money, $reson, $type = '', $from_id = 0, $field = 'money')
{
    if ($money == 0) return true;
    $fields = getMoneyFields();
    if ($field == 'all' || !isset($fields[$field])) return false;

    if (is_array($uid)) {
        throw new Exception('This method do not support batch uid');
    }

    $member = \think\Db::name('member')->field('id,username,' . $field)
        ->where('id', $uid)->find();
    $time = time();
    if ($money > 0) {
        $result = \think\Db::name('member')->where('id', $uid)
            ->setInc($field, $money);
        $log = [
            'create_time' => $time,
            'member_id' => $member['id'],
            'from_member_id' => $from_id,
            'type' => $type,
            'before' => $member[$field],
            'amount' => $money,
            'after' => $member[$field] + $money,
            'field' => $field,
            'reson' => $reson
        ];
    } else {
        $decMoney = abs($money);
        $result = \think\Db::name('member')->where('id', $uid)
            ->setDec($field, $decMoney);
        $log = [
            'create_time' => time(),
            'member_id' => $member['id'],
            'from_member_id' => $from_id,
            'type' => $type,
            'before' => $member[$field],
            'amount' => $money,
            'after' => $member[$field] + $money,
            'field' => $field,
            'reson' => $reson
        ];
    }
    if ($result) {
        return \think\Db::name('memberMoneyLog')->insert($log, false, true);
    } else {
        return false;
    }
}

function getPaytypes($type = '')
{

    $model = \think\Db::name('Paytype');
    if (!empty($type)) {
        $model->where('type', $type);
    }
    $lists = $model->select();
    return array_index($lists, 'id');
}

function getMemberParents($userid, $level = 5, $getid = true)
{
    return \app\common\model\MemberModel::getParents($userid, $level, $getid);
}

function getMemberSons($userid, $level = 1, $getid = true)
{
    return \app\common\model\MemberModel::getSons($userid, $level, $getid);
}

function getPageGroups($force = false)
{
    $groups = cache('page_group');
    if (empty($groups) || $force == true) {
        $groups = \think\Db::name('PageGroup')->order('sort ASC,id ASC')->select();
        cache('page_group', $groups);
    }
    return $groups;
}

/**
 * 获取全部配置
 * @param $all bool 是否全部数据
 * @param $group bool 是否分组
 * @param $parse bool 是否解析值 针对多选解析成数组
 * @return array
 */
function getSettings($all = false, $group = false, $parse = true)
{
    return \app\common\model\SettingModel::getSettings($all, $group, $parse);
}

function getSetting($key)
{
    $settings = getSettings();
    if (isset($settings[$key])) return $settings[$key];
    else return null;
}
function setSetting($key, $v)
{
    \think\Db::name('setting')->where('key', $key)->update(array('value' => $v));
    \app\common\model\SettingModel::clearCache();
}



/** =====================================  功能类函数  ===================================== **/

/**
 * 判断头像图片是否微信头像
 * 以确定更新用户资料时是否更新头像
 * @param $avatar
 * @return bool
 */
function is_wechat_avatar($avatar)
{
    if (empty($avatar)) {
        return false;
    }
    $nothttps = str_replace('https://', 'http://', $avatar);
    if (strpos($nothttps, 'http://thirdwx.qlogo.cn/') === 0) {
        return true;
    }
    if (strpos($nothttps, 'http://wx.qlogo.cn/') === 0) {
        return true;
    }

    return false;
}

function is_empty_avatar($avatar)
{
    if (empty($avatar)) {
        return true;
    }
    // wechat default avatar
    if (strpos($avatar, 'POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg') !== false) {
        return true;
    }
    return false;
}

/**
 * tp中已支持restore传入默认参数
 * @param string $default
 * @return $this|\think\response\Redirect
 */
function get_redirect($default = '')
{
    if (empty($default)) $default = url('index/member/index');
    return redirect()->restore($default);
}

function current_url($withqry = true)
{
    $query = $withqry ? $_REQUEST['QUERY_STRING'] : '';
    if (!empty($query)) $query = '?' . $query;
    return current_domain() . $_SERVER['REQUEST_URI'] . $query;
}

function current_domain()
{
    return rtrim(url('/', '', false, true), '/');
}

/**
 * 判断当前是否在某控制器内,并且不是某些action
 * @param string $controller 
 * @param array|string $except_methods 
 * @return bool 
 */
function is_controller($controller, $except_actions = [])
{
    if (is_string($except_actions)) {
        $except_actions = explode(',', $except_actions);
    }
    return strcasecmp(request()->controller(), $controller) == 0 && !in_array(request()->action(), $except_actions);
}

/**
 * 判断当前是否在某个控制器内的某些action
 * @param string $controller 
 * @param array|string $actions 
 * @return bool 
 */
function is_action($controller, $actions)
{
    if (is_string($actions)) {
        $actions = explode(',', $actions);
    }
    return strcasecmp(request()->controller(), $controller) == 0 &&
        in_array(request()->action(), $actions);
}

/**
 * 用于url的base64编码和解码功能
 * @param mixed $text 
 * @return string 
 */
function base64url_encode($text)
{
    if (empty($text)) return '';
    $base64 = base64_encode($text);
    $base64url = strtr($base64, '+/=', '-_,');
    return $base64url;
}

function base64url_decode($text)
{
    if (empty($text)) return '';
    $base64url = strtr($text, '-_,', '+/=');
    $base64 = base64_decode($base64url);
    return $base64;
}

/**
 * 带权重的数组随机
 * @param $array
 * @param string $wfield
 * @param bool $order 正向权重
 * @return array
 */
function weight_random($array, $wfield = 'weight', $order = true)
{

    $row = [];
    if (empty($array)) return $row;
    if (!$order) {
        $max = max(array_column($array, $wfield));
        $pow = pow(10, ceil(log10($max)));
        $ofield = $wfield;
        $wfield = '_new_' . $wfield;
        foreach ($array as &$row) {
            $row[$wfield] = $row[$ofield] == 0 ? $pow : ($pow / $row[$ofield]);
        }
        unset($row);
    }
    $total = array_sum(array_column($array, $wfield));
    $randmax = min($total * 1000, mt_getrandmax());
    $rand = mt_rand(0, $randmax);
    $rand = $rand * $total / $randmax;
    $sum = 0;
    foreach ($array as $row) {
        $sum += $row[$wfield];
        if ($sum >= $rand) {
            return $row;
        }
    }
    return $row;
}

/**
 * 替换数组中的一个或几个键名对应的值
 * @param $key
 * @param $val
 * @param string $search
 * @return array|mixed|string
 */
function searchKey($key, $val, $search = '')
{
    if (!is_array($search)) {
        $search = request()->param();
    }
    if (isset($search['page'])) {
        unset($search['page']);
    }
    if (strpos($key, ',') > 0) {
        $keys = explode(',', $key);
        foreach ($keys as $key) {
            $search = searchKey(trim($key), $val, $search);
        }
    } else {
        if (empty($val) || $val == 'all') {
            if (isset($search[$key])) unset($search[$key]);
        } else {
            $search[$key] = $val;
        }
    }
    return $search;
}

/**
 * 过滤特殊字符
 * 主要用于搜索关键字的过滤
 * @param $str
 * @return mixed
 */
function filter_specchar($str)
{
    return preg_replace("/\/|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|/", '', $str);
}

/**
 * id参数转换成数组
 * 用于数据库主键批量操作
 * @param $id
 * @return array
 */
function idArr($id)
{
    if (is_array($id)) {
        return array_map(function ($i) {
            return intval($i);
        }, $id);
    }
    if (strpos($id, ',') > 0) {
        $ids = explode(',', $id);
        return array_map(function ($i) {
            return intval($i);
        }, $ids);
    } elseif (!empty($id)) {
        return [intval($id)];
    }
    return [];
}

function numberArr($id)
{
    if (is_array($id)) {
        return array_map(function ($i) {
            return floatval($i);
        }, $id);
    }
    if (strpos($id, ',') > 0) {
        $ids = explode(',', $id);
        return array_map(function ($i) {
            return floatval($i);
        }, $ids);
    } else {
        return [floatval($id)];
    }
}

/**
 * 检测文件编码
 * @param string $file 文件路径
 * @return string|null 返回 编码名 或 null
 */
function detect_encoding($file)
{
    $list = array('GB2312', 'GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1');
    $str = file_get_contents($file);
    foreach ($list as $item) {
        $tmp = mb_convert_encoding($str, $item, $item);
        if (md5($tmp) == md5($str)) {
            return $item;
        }
    }
    return null;
}

/**
 * 自动解析编码读入文件
 * @param string $file 文件路径
 * @param string $charset 读取编码
 * @return string 返回读取内容
 */
function auto_read($file, $charset = 'UTF-8')
{
    $list = array('GB2312', 'GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1');
    $str = file_get_contents($file);
    foreach ($list as $item) {
        $tmp = mb_convert_encoding($str, $item, $item);
        if (md5($tmp) == md5($str)) {
            return mb_convert_encoding($str, $charset, $item);
        }
    }
    return "";
}

/**
 * 索引二维数组
 * @param $arr array 二维数组
 * @param $index  string  索引
 * @param bool $ismulti 一对多模式
 * @return array
 */
function array_index($arr, $index, $ismulti = false)
{
    $return = [];
    if (!empty($arr)) {
        $val = '';
        if (strpos($index, ',') > 0) {
            $indexes = explode(',', $index);
            $index = trim($indexes[0]);
            $val = trim($indexes[1]);
        }
        foreach ($arr as $row) {
            if ($ismulti) {
                $return[$row[$index]][] = empty($val) ? $row : $row[$val];
            } else {
                $return[$row[$index]] = empty($val) ? $row : $row[$val];
            }
        }
    }
    return $return;
}

define('COMBINE_PAD_NONE', 0);
define('COMBINE_PAD_VALUE', 1);
define('COMBINE_PAD_KEY', 2);
/**
 * 兼容的array_combine
 * @param array $keys
 * @param array $vals
 * @param int $pad_mode
 * @param int|string|mixed $value_default
 * @param string $key_prefix
 * @return array
 */
function array_combine_cmp($keys, $vals, $pad_mode = 0, $value_default = "", $key_prefix = 'extra_field_')
{
    $kcount = count($keys);
    $vcount = count($vals);
    if (!$pad_mode) {
        if ($kcount > $vcount) {
            $keys = array_slice($keys, 0, $vcount);
        } elseif ($kcount < $vcount) {
            $vals = array_slice($vals, 0, $kcount);
        }
    } else {
        // more headers than row fields
        if ($kcount > $vcount && ($pad_mode & COMBINE_PAD_VALUE) == COMBINE_PAD_VALUE) {
            // how many fields are we missing at the end of the second array?
            // Add empty strings to ensure arrays $a and $b have same number of elements
            $more = $kcount - $vcount;
            for ($i = 0; $i < $more; $i++) {
                $vals[] = $value_default;
            }
            // more fields than headers
        } else if ($kcount < $vcount && ($pad_mode & COMBINE_PAD_KEY) == COMBINE_PAD_KEY) {
            $more = $vcount - $kcount;
            // fewer elements in the first array, add extra keys
            for ($i = 0; $i < $more; $i++) {
                $key = $key_prefix . $i;
                $keys[] = $key;
            }
        }
    }

    return array_combine($keys, $vals);
}

function implode_cmp($arr, $glue = ',')
{
    if (is_array($arr)) {
        return implode($glue, $arr);
    }
    return '';
}

function fix_in_array($val, $arr)
{
    if (empty($arr)) return false;
    return in_array($val, (array)$arr);
}

function array_max($arr, $column)
{
    if (empty($arr)) return 0;
    $data = array_column($arr, $column);
    return max($data);
}
function array_min($arr, $column)
{
    if (empty($arr)) return 0;
    $data = array_column($arr, $column);
    return min($data);
}

function is_assoc_array($array)
{
    return array_keys($array) !== range(0, count($array) - 1);
}

function encode_password($pass, $salt = '')
{
    return sha1(PASSWORD_HASH_PREFIX . md5($pass) . $salt);
}

function compare_password($user, $password)
{
    return encode_password($password, $user['salt']) === $user['password'];
}

function compare_secpassword($user, $password)
{
    return encode_password($password, $user['secsalt']) === $user['secpassword'];
}


function camelize($uncamelized_words, $separator = '_')
{
    $uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words));
    return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator);
}

function ucfcamelize($uncamelized_words, $separator = '_')
{
    $uncamelized_words =  str_replace($separator, " ", strtolower($uncamelized_words));
    return str_replace(" ", "", ucwords($uncamelized_words));
}

function uncamelize($str, $separator = '_')
{
    return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $str));
}

function random_str($length = 6, $type = 'string', $convert = 0)
{
    $config = array(
        'number' => '1234567890',
        'letter' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
        'string' => 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789',
        'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    );

    if (!isset($config[$type])) $type = 'string';
    $string = $config[$type];

    $code = '';
    $strlen = strlen($string) - 1;
    for ($i = 0; $i < $length; $i++) {
        if ($type != 'number' && $i == 0) {
            $code .= $config['letter'][mt_rand(0, $strlen - 8)];
        } else {
            $code .= $string[mt_rand(0, $strlen)];
        }
    }
    if (!empty($convert)) {
        $code = ($convert > 0) ? strtoupper($code) : strtolower($code);
    }
    return $code;
}

/**
 * 获取排序后的分类
 * @param  array $data [description]
 * @param  integer $pid [description]
 * @param  string $pre [description]
 * @return array
 */
function getSortedCategory(&$data, $pid = 0, $pre = "", $level = 0, &$count = 0)
{
    $temp = array();
    $curdata = array_filter($data, function ($item) use ($pid) {
        return $item['pid'] == $pid;
    });

    $count = count($curdata);

    $idx = 0;
    foreach ($curdata as $v) {
        $idx++;
        $islast = $idx == $count ? true : false;
        $v['islast'] = $islast;
        $v['html'] = $islast ? ($pre . '└─') : ($pre . '├─');
        $v['level'] = $level;
        $subcount = 0;
        if ($islast) {
            $sublist = getSortedCategory($data, $v['id'], $pre . '　　', $level + 1, $subcount);
        } else {
            $sublist = getSortedCategory($data, $v['id'], $pre . '│　', $level + 1, $subcount);
        }
        $v['count'] = $subcount;
        $temp[] = $v;
        $temp = array_merge($temp, $sublist);
    }
    return $temp;
}


function format_date($date_str, $format)
{
    $time = strtotime($date_str);
    if ($time > 0) {
        return date($format, $time);
    }
    return '';
}

function number_empty($val)
{
    $tval = floatval($val);
    return empty($tval) ? '' : $val;
}

/**
 * curl下载文件
 * @param mixed $durl 
 * @return string|bool 
 */
function curl_file_get_contents($durl, $timeout = 3, $referer = '')
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $durl);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36');
    curl_setopt($ch, CURLOPT_REFERER, $referer);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $r = curl_exec($ch);
    curl_close($ch);
    return $r;
}

/**
 * 请求接口返回内容
 * @param $url string  [请求的URL地址]
 * @param $params string|bool [请求的参数]
 * @param $ispost int [是否采用POST形式]
 * @return string
 */
function http_request($url, $params = false, $ispost = 0)
{
    $httpInfo = array();
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'JuheData');
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    if (stripos($url, "https://") !== FALSE) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //curl_setopt($ch, CURLOPT_SSLVERSION, 1);
    }
    if (is_array($params)) {
        $params = http_build_query($params);
    }
    if ($ispost) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        curl_setopt($ch, CURLOPT_URL, $url);
    } else {
        if ($params) {
            curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
        } else {
            curl_setopt($ch, CURLOPT_URL, $url);
        }
    }
    $response = curl_exec($ch);
    if ($response === FALSE) {
        //echo "cURL Error: " . curl_error($ch);
        return false;
    }
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $httpInfo = array_merge($httpInfo, curl_getinfo($ch));
    curl_close($ch);
    return $response;
}


function gener_qrcode($text, $size = 300, $margin = 10, $errLevel = \Endroid\QrCode\ErrorCorrectionLevel::High)
{
    $builder = new \Endroid\QrCode\Builder\Builder();

    $result = $builder->writer(new \Endroid\QrCode\Writer\PngWriter())
        ->encoding(new \Endroid\QrCode\Encoding\Encoding('UTF-8'))
        ->data($text)
        ->size($size)
        ->margin($margin)
        ->errorCorrectionLevel($errLevel)
        ->foregroundColor(new \Endroid\QrCode\Color\Color(0,  0,  0))
        ->backgroundColor(new \Endroid\QrCode\Color\Color(255,  255,  255))
        //->labelText('thinkphp.cn')
        //->labelFont(new NotoSans(16))
        ->build();;
    return $result->getString();
}

function file_rule($file)
{
    static $stamp = '';
    if (!$stamp) $stamp = microtime();
    else $stamp += 1;
    return md5(md5_file($file) . $stamp);
}

function crop_image($file, $options)
{
    $imageCrop = new \extcore\ImageCrop($file, $options);
    return $imageCrop->crop();
}

//end file